package 链表

/*
https://leetcode.cn/problems/copy-list-with-random-pointer/?envType=study-plan-v2&envId=top-100-liked


138. 随机链表的复制
给你一个长度为 n 的链表，每个节点包含一个额外增加的随机指针 random ，该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成，其中每个新节点的值都设为其对应的原节点的值。
新节点的 next 指针和 random 指针也都应指向复制链表中的新节点，并使原链表和复制链表中的这些指针能够表示相同的链表状态。
复制链表中的指针都不应指向原链表中的节点 。

例如，如果原链表中有 X 和 Y 两个节点，其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ，同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示：
val：一个表示 Node.val 的整数。
random_index：随机指针指向的节点索引（范围从 0 到 n-1）；如果不指向任何节点，则为  null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。

示例 1：
输入：head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出：[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2：
输入：head = [[1,1],[2,1]]
输出：[[1,1],[2,1]]

示例 3：
输入：head = [[3,null],[3,0],[3,null]]
输出：[[3,null],[3,0],[3,null]]
*/

type Node struct {
	Val    int
	Next   *Node
	Random *Node
}

func copyRandomList(head *Node) *Node {
	if head == nil {
		return nil
	}

	nodeMap := make(map[*Node]*Node) // 创建一个映射来保存原始节点和新节点之间的映射关系

	curr := head // 第一步：遍历原始链表，为每个节点创建一个新节点，并存入映射中
	for curr != nil {
		newNode := &Node{Val: curr.Val}
		nodeMap[curr] = newNode
		curr = curr.Next
	}

	curr = head // 第二步：设置新节点的next和random指针
	for curr != nil {
		if newNode, ok := nodeMap[curr]; ok {
			if nextNode, ok := nodeMap[curr.Next]; ok { // 设置新节点的next指针
				newNode.Next = nextNode
			}
			if randomNode, ok := nodeMap[curr.Random]; ok { // 设置新节点的random指针
				newNode.Random = randomNode
			}
		}
		curr = curr.Next
	}

	return nodeMap[head] // 返回新链表的头节点
}
